package com.maimao.auth.service;

import com.maimao.auth.client.CompanyClient;
import com.maimao.auth.client.SysUserClient;
import com.maimao.auth.client.UserClient;
import com.maimao.auth.model.SysAuthUser;
import com.maimao.core.constant.Constants;
import com.maimao.core.model.resp.Result;
import com.maimao.model.user.sys.vo.Permissions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 用户名密码认证
 */
@Component("baseUserDetailsService")
@Slf4j
public class BaseUserDetailsService implements MMUserDetailsService {


    public static final String MEMBER = "member";
    public static final String COMPANY = "company";
    public static final String SYS = "sys";

    public BaseUserDetailsService(SysUserClient sysUserClient, UserClient userClient, CompanyClient companyClient, ClientDetailsService clientDetailsService) {
        this.sysUserClient = sysUserClient;
        this.userClient = userClient;
        this.companyClient = companyClient;
        this.clientDetailsService = clientDetailsService;
    }


    @Override
    public UserDetails loadUserByUsername(String usernameOrMobileOrEmail) throws UsernameNotFoundException {
        UserDetails clientSecret = loadClientDetails(usernameOrMobileOrEmail);
        if (clientSecret != null) {
            return clientSecret;
        }
        if (StringUtils.isEmpty(usernameOrMobileOrEmail)) {
            return null;
        }
        Result<Permissions> result = findUserByUserName(usernameOrMobileOrEmail);
        return getSysAuthUser(result);
    }

    @Override
    public UserDetails loadUserByMobile(String mobile) {
      /*  UserDetails clientSecret = loadClientDetails(mobile);
        if (clientSecret != null) return clientSecret;*/
        if (StringUtils.isEmpty(mobile)) {
            return null;
        }
        Result<Permissions> result = findUserByMobile(mobile);
        return getSysAuthUser(result);
    }

    @Override
    public UserDetails loadUserByEmail(String email) {
       /* UserDetails clientSecret = loadClientDetails(email);
        if (clientSecret != null) return clientSecret;*/
        if (StringUtils.isEmpty(email)) {
            return null;
        }
        Result<Permissions> result = findUserByEmail(email);
        SysAuthUser sysAuthUser = getSysAuthUser(result);
        return sysAuthUser;
    }

    /**
     * 根据邮箱查询权限(会员和企业用户)
     *
     * @param email
     * @return Result<Permissions>
     */
    private Result<Permissions> findUserByEmail(String email) {
        String userType = getUserType();
        log.info("获取到用户类型{}", userType);
        Result<Permissions> result = null;
        if (userType == null) {
            return null;
        }
        if (userType.equals(MEMBER)) {
            result = userClient.getMemberPermissionByEmail(email);
        } else if (userType.equals(COMPANY)) {
            result = companyClient.getCompanyPermissionByEmail(email);
        }
        return result;
    }

    /**
     * 根据手机号查询权限
     */
    private Result<Permissions> findUserByMobile(String mobile) {

        String type = getUserType();
        log.info("获取到用户类型{}", type);
        //目前只能普通用户进行手机登录 企业用户只允许邮箱登录
        return userClient.getMemberPermissionByMobile(mobile);
    }

    /**
     * 根据用户名查询权限信息 只允许后台用户和会员用于 企业用户不可根据用户名登录
     */
    private Result<Permissions> findUserByUserName(String usernameOrMobileOrEmail) {

        String type = getUserType();
        log.info("获取到用户类型{}", type);
        Result<Permissions> result = null;
        if (type == null) {
            return null;
        } else if (type.equals(SYS)) {
            result = sysUserClient.getPermissionByUserName(usernameOrMobileOrEmail);
        } else if (type.equals(MEMBER)) {
            result = userClient.getMemberPermissionByUsername(usernameOrMobileOrEmail);
        }

        return result;
    }


    private SysAuthUser getSysAuthUser(Result<Permissions> result) {
        if (result.getData() == null) {
            return null;
        }
        Permissions permissions = result.getData();
        String permissionStr = permissions.getPermissionStr();
        SysAuthUser sysAuthUser = new SysAuthUser(permissions.getUsername(),
                permissions.getPassword(),
                AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.isEmpty(permissionStr) ? Constants.EMPTY : permissionStr));
        sysAuthUser.setId(permissions.getId() + "");
        sysAuthUser.setShopId(permissions.getShopId());
        sysAuthUser.setRealName(permissions.getRealName());
//        sysAuthUser.setAvatar(permissions.getAvatar());
        String userType = getUserType();
        /*if (!userType.equals(SYS)) {
            List<String> roles = permissions.getRoles();
            StringBuilder sb = new StringBuilder();
            if (roles != null && roles.size() > 0) {
                for (String role : roles) {
                    sb.append(role.substring(5)).append(Constants.UNDER_LINE_STR);
                }
            }

            String roleStr = sb.toString();
            sysAuthUser.setRole(userType);
            sysAuthUser.setType(StringUtils.substringBeforeLast(roleStr, Constants.UNDER_LINE_STR));
        } else {
            sysAuthUser.setType(getUserType());
            sysAuthUser.setRole(getUserType());
        }*/
        List<String> roles = permissions.getRoles();
        StringBuilder sb = new StringBuilder();
        if (roles != null && roles.size() > 0) {
            for (String role : roles) {
                sb.append(role.substring(5)).append(Constants.UNDER_LINE_STR);
            }
        }

        String roleStr = sb.toString();
        sysAuthUser.setRole(userType);
        sysAuthUser.setType(StringUtils.substringBeforeLast(roleStr, Constants.UNDER_LINE_STR));
        return sysAuthUser;
    }

    public String getUserType() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return request.getParameter(Constants.LOGIN_TYPE);
    }

    /**
     * 落入/oauth/token前 会在BasicAuthenticationFilter过滤器中调用loadUserByUsername，在这里验证客户端
     *
     * @param usernameOrMobileOrEmail 用户名或手机或邮箱
     * @return UserDetails
     */
    private UserDetails loadClientDetails(String usernameOrMobileOrEmail) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 没有认证统一采用httpbasic认证，httpbasic中存储了client_id和client_secret，开始认证client_id和client_secret
        if (authentication == null) {
            ClientDetails clientDetails = clientDetailsService.loadClientByClientId(usernameOrMobileOrEmail);
            if (clientDetails != null) {
                // 密码
                String clientSecret = clientDetails.getClientSecret();
                return new User(usernameOrMobileOrEmail, clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(""));
            }
        }
        return null;
    }

    private final SysUserClient sysUserClient;

    private final UserClient userClient;

    private final CompanyClient companyClient;

    final ClientDetailsService clientDetailsService;

}
